(ns server.server
		"This is the class that acts as a server and performs given requests"
(:gen-class)
(:use clojure.contrib.duck-streams user.newMenu server.dbmain user.commonFunctions)
(:import (java.net Socket ServerSocket)
(java.io PrintWriter File FileInputStream FileOutputStream)
(java.util Scanner)
(javax.swing JFrame JTable)))

(def *port2* 3003)
(def *input* "db-1x2.db")

(defn send-msg
		"Sends msg through out
		 msg -- message to be sent
		 out -- socket Output Stream through which the msg will be sent"
		[msg out]
        (.println out msg)
        (.flush out)
)

;;------------------------------------------------------------------------------------------------------------------------------------

(defn copy-database
	"Makes a copy of the current database and sends it to the client
	 socket -- socket used to send the copied database"
	[socket]
	(with-open [
		input (Scanner. (.getInputStream socket))
		input-stream  (FileInputStream. (File. *input*))
		output-stream (.getOutputStream socket)
		]
		(let [buffer (byte-array 1024)]
			(loop [len (.read input-stream buffer)]
				(if (> len 0)
					(do
						(.write output-stream buffer, 0, len)
						(recur (.read input-stream buffer))
					)
				)
			)
		)
		(.nextLine input)
	)
)

;;------------------------------------------------------------------------------------------------------------------------------------

(defn server-reload
	"Runs the server-side protocol that reloads the clients' database"
	[socket]
	(copy-database socket)
)

;;------------------------------------------------------------------------------------------------------------------------------------

(defn server-add
		"Runs the server-side protocol that adds a new record into the server's 
		database and sends it back to the client."
		[socket]
		(let [ model (table-model)
			   table (JTable. model)
			   data	{:name (str) :location (str) :rate (str) 
			   :date (str) :size (str) :smoking (str) :owner (str)}
			   new-rec-number (create-record 
			   		   *input*
			   		   {:name "" :location "" :rate "$00.00" 
    	  	  		 	:date "2010/01/01" :size "0" :smoking "N" :owner ""})]
        		(addRow-table
        			new-rec-number
        			(assoc data :deleted "false") 		
    	  	  		model)
        	)
)           

;;------------------------------------------------------------------------------------------------------------------------------------

(defn server-delete
	"Runs the server-side protocol that deletes a record"
	[socket]
	(with-open [input (Scanner. (.getInputStream socket))
		output (PrintWriter. (.getOutputStream socket))
		]
		(delete-record *input* (.nextInt input))
		(.println output "ok")
	)
)

(defn server-update
	"Runs the server-side protocol that updates a record"
	[socket]
	(with-open [input (Scanner. (.getInputStream socket))
		output (PrintWriter. (.getOutputStream socket))
		]
		(let [rec-no (.nextInt input)
			quak (.nextLine input)
			nme (.nextLine input)
			loc (.nextLine input)
			rte (.nextLine input)
			own (.nextLine input)
			dat (.nextLine input)
			sze (.nextLine input)
			smo (.nextLine input)
			new-data {:name nme :location loc :rate rte
				:owner own :date dat :size sze :smoking smo}]
				(update-record *input* rec-no new-data)
		)
	)
)

(defn agent-actions
		"Actions made by the agent attending the current request.
		 ag -- agent in this thread
		 socket -- socket used for this request"
  [ag socket]
  (let [pet (atom "")]
  	  (with-open [input  (.getInputStream socket)
  	  	  output (PrintWriter. (.getOutputStream socket))]
          (loop []
          	  (let [c (.read input)]
            	  (when (and (not= -1 c) (not (empty? (.trim (str (char c))))))
            	  	  (reset! pet (do 
          	  				(apply str (concat @pet (.trim (str (char c)))))))
              (recur)
          )))
          
  		  (if (= "connection" @pet) (copy-database socket))
  		  (if (= "give-me-the-database" @pet) (server-reload socket))
  		  (if (= "create-new-record" @pet) (server-add socket))
  		  (if (= "delete-record" @pet) (server-delete socket))
  		  (if (= "update-record" @pet) (server-update socket))
  	  )
  )
  
  )
                                      
;;------------------------------------------------------------------------------------------------------------------------------------

(defn serve
		"Attends petitions using an agent and sendign it to fulfill a request"
  []
  (let [servidor       (ServerSocket. *port2*)
        agente         (agent nil)]
    (loop []
      (println "Waiting for conection...")
      (let [socket (.accept servidor)]
        (send-off agente agent-actions socket)
        (await-for 1000 agente)
        (clear-agent-errors agente)
      (recur)))
    )
)
